﻿using System.Xml;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Configuration;

using umbraco.cms.businesslogic.packager.standardPackageActions;
using umbraco.interfaces;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.template;
using umbraco.cms.businesslogic.datatype;
using umbraco.cms.businesslogic.propertytype;

namespace Ulriksen.Umbraco.OpenId
{
    /// <summary>
    /// This Package action will Add a new rule to the UrlRewriting.config file
    /// </summary>
    /// <remarks>
    /// This package action is part of the PackageActionsContrib Project
    /// </remarks>
    public class OpenIdPackageAction : IPackageAction
    {

        #region IPackageAction Members

        /// <summary>
        /// This Alias must be unique and is used as an identifier that must match the alias in the package action XML
        /// </summary>
        /// <returns>The Alias in string format</returns>
        public string Alias()
        {
            return "OpenIdPackageAction";
        }

        /// <summary>
        /// Update the node id on the contacts page. 
        /// </summary>
        /// <param name="packageName">Name of the package that we install</param>
        /// <param name="xmlData">The data that must be appended to the UrlRewriting.config file</param>
        /// <returns>True when succeeded</returns>
        public bool Execute(string packageName, System.Xml.XmlNode xmlData)
        {

            bool result = false;
            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            try
            {
                //Set result default to false
                sb.AppendLine("CREATE TABLE [dbo].[nuMemberOpenid](");
                sb.AppendLine("[OpenId] [varchar](255) NOT NULL,");
                sb.AppendLine("[nodeId] [int] NOT NULL,");
                sb.AppendLine("CONSTRAINT [PK_nuMemberOpenid] PRIMARY KEY CLUSTERED ");
                sb.AppendLine("(");
                sb.AppendLine("	[OpenId] ASC");
                sb.AppendLine(")WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]");
                sb.AppendLine(")");

                Application.SqlHelper.ExecuteNonQuery(sb.ToString());

                try
                {
                    sb = new System.Text.StringBuilder();

                    sb.AppendLine("CREATE TRIGGER [CascadeDeleteOpenId]");
                    sb.AppendLine("ON  [dbo].[cmsMember]");
                    sb.AppendLine("AFTER DELETE");
                    sb.AppendLine("AS ");
                    sb.AppendLine("BEGIN");
                    sb.AppendLine("SET NOCOUNT ON;");
                    sb.AppendLine("delete from nuMemberOpenId where nodeId in (select nodeId from deleted)");
                    sb.AppendLine("END");
                }
                catch (System.Exception ex)
                {
                    umbraco.BusinessLogic.Log.Add(LogTypes.Debug, 0, "Unable to add delete member trigger for OpenId cleanup. This will be handled by deletemember event instead. " + ex.ToString());
                }

                Application.SqlHelper.ExecuteNonQuery(sb.ToString());

                User systemUser = new User(0);
                umbraco.cms.businesslogic.member.MemberGroup group = umbraco.cms.businesslogic.member.MemberGroup.MakeNew("OpenIdMemberGroup", systemUser);
                group.Save();

                //DataTypeDefinition[] dataTypes = umbraco.cms.businesslogic.datatype.DataTypeDefinition.GetAll();
                DataTypeDefinition boolDataType = null;
                //foreach (DataTypeDefinition dataType in dataTypes)
                //    if (dataType.DataType.DataTypeName.StartsWith("True/False")) 
                //        boolDataType = dataType;

                boolDataType = new DataTypeDefinition(-49);

                MemberType type = MemberType.MakeNew(systemUser, "OpenIdMemberType");
                PropertyType propType = PropertyType.MakeNew(boolDataType, type, "Is OpenId Member", "isOpenIdMember");
                propType.Save();
                type.Save();


                //Check for runway
                Document[] docs = Document.GetRootDocuments();

                
                foreach (Document doc in docs)
                    if (doc.Text == "Runway Homepage")
                    {
                        //add login template to document type
                        DocumentType docType = DocumentType.GetByAlias("RunwayTextpage");
                        Template loginTemplate = Template.GetByAlias("Runway OpenId Login");
                        
                        List<Template> templates = new List<Template>();
                        templates.AddRange(docType.allowedTemplates);
                        templates.Add(loginTemplate);

                        docType.allowedTemplates = templates.ToArray();
                        docType.Save();


                        //create documents
                        User user = new umbraco.BusinessLogic.User(0);

                        Document myOpenIds = Document.MakeNew("My OpenIds", docType, user, doc.Id );
                        foreach (var property in myOpenIds.getProperties)
                        {
                            if (property.PropertyType.Alias == "bodyText")
                                property.Value = "<p>This is a list of the id's associated with your acocunt.</p><?UMBRACO_MACRO macroAlias=\"OpenIdMyIds\" />";

                            if (property.PropertyType.Alias == "umbracoNaviHide")
                                property.Value = 0;
                        }
                        myOpenIds.Template = docType.DefaultTemplate;
                        myOpenIds.Publish(user);
                        umbraco.library.UpdateDocumentCache(myOpenIds.Id);

                        Document login = Document.MakeNew("Login / Register", docType, user, doc.Id);
                        login.Template = loginTemplate.Id;
                        foreach (var property in login.getProperties)
                        {
                            if (property.PropertyType.Alias == "bodyText")
                                property.Value = "<p>If you do not have an OpenId you can <a href=\"http://openid.net/get-an-openid/\" target=\"_blank\" title=\"Get an OpenId\">obtain one</a> from the OpenId provider of your choice.</p>";

                            if (property.PropertyType.Alias == "umbracoNaviHide")
                                property.Value = 0;
                        }
                        login.Publish(user);
                        umbraco.library.UpdateDocumentCache(login.Id);
                        

                        umbraco.library.RefreshContent();

                        ProtectPage(myOpenIds.Id,login.Id);

                    }

                result = true;

                Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
                MembershipSection configSection = (MembershipSection)config.GetSection("system.web/membership");

                //check if memberty has been configured. Do not touch config if member type exist.
                string memberTypeAlias = configSection.Providers["UmbracoMembershipProvider"].Parameters["defaultMemberTypeAlias"];
                MemberType[] memberTypes = umbraco.cms.businesslogic.member.MemberType.GetAll;
                bool memberFound = false;
                foreach (MemberType memberType in memberTypes)
                    if (memberType.Alias == memberTypeAlias)
                        memberFound = true;

                if (!memberFound)
                {
                    configSection.Providers["UmbracoMembershipProvider"].Parameters["defaultMemberTypeAlias"] = "OpenIdMemberType";
                    config.Save();
                }



            }
            catch (System.Exception ex)
            {
                Log.Add(LogTypes.Error, 0, "Error in OpenId package action. " + ex.ToString());
                Log.Add(LogTypes.Error, 0, sb.ToString());
            }





            return result;
        }

        private void ProtectPage(int protectId, int loginId)
        {

            umbraco.cms.businesslogic.web.Access.ProtectPage(false, protectId, loginId, loginId);
            umbraco.cms.businesslogic.web.Access.AddMembershipRoleToDocument(protectId, "OpenIdMemberGroup");

        }

        /// <summary>
        /// As we only update property of a document WE created, we can ignore undo.
        /// </summary>
        /// <param name="packageName">Name of the package that we install</param>
        /// <param name="xmlData">The data that must be appended to the UrlRewriting.config file</param>
        /// <returns>True when succeeded</returns>
        public bool Undo(string packageName, System.Xml.XmlNode xmlData)
        {

            return true;
        }

        /// <summary>
        /// Returns a Sample XML Node 
        /// In this case the Sample XML Rule for the CWS2 Email friend functionality
        /// </summary>
        /// <returns>The sample xml as node</returns>
        public XmlNode SampleXml()
        {
            string sample = "<Action runat=\"install\" undo=\"false\" alias=\"OpenIdPackageAction\"></Action>";
            return helper.parseStringToXmlNode(sample);
        }

        #endregion

    }
}
